Liberal Democrat UBI Policy Paper: An Analysis

The Liberal Democrat Working Group in May 2021 published a new policy paper exploring possible universal basic income policies for the party’s future platform, without committing to any particular one. The paper is available here. This release was within the context of the September Liberal Democrat Conference vote to campaign for universal basic income in future elections. The findings from the Working Group’s paper were presented by Paul Noblet, the chair, in the Social Liberal Forum event What Kind of UBI?, chaired by Jon Alexander, in which Jane Dodds (Leader of the Liberal Democrats in Wales), Christine Jardine (Liberal Democrat MP for Edinburgh West) and Max Ghenis (Founder of the UBI Center) gave first responses to the proposals. The event is available as a recording here.

The policy paper outlines four different UBI levels, each with different net costs after UBI and tax-benefit changes. The tax changes are predominantly reductions in thresholds and allowances rather than rate increases, and the benefit changes involve including UBI in means tests. Both of these recoup a significant amount of the UBI expenditure, but in all cases leave a non-trivial net cost ranging between £13bn and £93bn per year. The UBI Center has reproduced these analyses using the open-sourced microsimulation model OpenFisca-UK in order to provide additional household-level information such as poverty effects, distributional changes and changes to marginal tax rates.

Reform effects

All four of the reforms produce positive results on poverty, inequality and other social metrics. They are progressive in that benefits largely start high and decrease with income, though this is complicated slightly by benefit reductions from UBI payments, which reduce the gains of benefit recipients.

Funding breakdown

Below specifies the second reform, and calculates the effects of each component under the household-level simulation. This is a £60/week UBI for working-age adults, funded in part by including it in benefit means tests1, reducing the Personal Allowance for working-age adults and reducing the National Insurance Primary Threshold to £50/week. Overall, the Personal Allowance provides most of the funding, and the inclusion in means tested benefits provides only a small part that could be covered by reducing the personal allowance further.

from openfisca_uk import Microsimulation
from reform import WA_adult_UBI, include_UBI_in_means_tests, set_PA, set_PA_for_WA_adults, set_PT, net_cost
import numpy as np
import pandas as pd
from tqdm import trange, tqdm

funding = (set_PA_for_WA_adults(2500), set_PT(50), include_UBI_in_means_tests())
ubi_60 = (WA_adult_UBI(60 * 52), *funding)
baseline = Microsimulation(year=2020)
ubi_60_sim = Microsimulation(ubi_60, year=2020)

net_costs = []
names = ["UBI", "Lower PA", "Lower PT", "Reduced benefits"]
for i in range(len(ubi_60) + 1):
    net_costs += [net_cost(baseline, Microsimulation(ubi_60[:i], year=2020))]
net_costs = np.array(net_costs)

resulting_costs = pd.Series(net_costs[1:] - net_costs[:-1])
reform_tax_revenue = -resulting_costs[1] - resulting_costs[2]
resulting_costs = resulting_costs.apply(lambda x : round(x / 1e+9, 1))

pd.DataFrame({"Component": names, "Net cost (£bn)": resulting_costs, "Resulting net cost (£bn)": resulting_costs.cumsum()}).set_index("Component")
Net cost (£bn) Resulting net cost (£bn)
Component
UBI 126.9 126.9
Lower PA -60.7 66.2
Lower PT -19.1 47.1
Reduced benefits -12.8 34.3

UBI variants

The policy paper looks at four UBI proposals, characterized mainly by their UBI level: £45, £60, £75 and £95 per week. The below table shows the estimated cost of the reforms. The tax changes are the same in the last three reforms, but the first reform uses a higher Personal Allowance (£4000/year) and Primary Threshold (£90/week), increasing the cost[^2] but significantly decreasing the share who lose out. Below is a table showing the effects of all reforms on poverty, deep poverty and inequality, as well as the winner and loser share (among the entire population).

[^2] This adjustment adds around £8bn to the net cost of the scheme.

ubi_45 = (WA_adult_UBI(45 * 52), set_PA_for_WA_adults(4000), set_PT(90), include_UBI_in_means_tests())
ubi_75 = (WA_adult_UBI(75 * 52), funding)
ubi_95 = (WA_adult_UBI(95 * 52), funding)

from openfisca_uk.api import *

def get_results(reform: Reform):
    sim = Microsimulation(reform, year=2020)
    cost = net_cost(baseline, sim)
    ubi_cost = sim.calc("UBI").sum()
    benefit_revenue = ubi_cost - reform_tax_revenue - cost
    baseline_poverty = baseline.calc("in_poverty_bhc", map_to="person").mean()
    baseline_deep_poverty = baseline.calc("in_deep_poverty_bhc", map_to="person").mean()
    poverty_change = (sim.calc("in_poverty_bhc", map_to="person").mean() - baseline_poverty) / baseline_poverty
    deep_poverty_change = (sim.calc("in_deep_poverty_bhc", map_to="person").mean() - baseline_deep_poverty) / baseline_deep_poverty
    baseline_gini = baseline.calc("household_net_income", map_to="person").gini()
    inequality_change = (sim.calc("household_net_income", map_to="person").gini() - baseline_gini) / baseline_gini
    baseline_income = baseline.calc("household_net_income", map_to="person")
    gain = sim.calc("household_net_income", map_to="person") - baseline_income
    percent_winners = (gain > 0).mean()
    percent_losers = (gain < 0).mean()
    return sim, cost, poverty_change, deep_poverty_change, inequality_change, percent_winners, percent_losers, ubi_cost, benefit_revenue

reforms = (ubi_45, ubi_60, ubi_75, ubi_95)
names = ("£45", "£60", "£75", "£95")
results = list(map(get_results, reforms))
sims, costs, poverty_changes, deep_poverty_changes, inequality_changes, percent_winners, percent_losers, ubi_cost, benefit_revenue = list(zip(*results))
LD_lower = (13, 22, 48, 84)
LD_upper = (18, 28, 56, 93)
pd.DataFrame({
    "UBI": names, 
    "Poverty change (%)": pd.Series(poverty_changes).apply(lambda x: round(x * 100, 1)),
    "Deep poverty change (%)": pd.Series(deep_poverty_changes).apply(lambda x: round(x * 100, 1)),
    "Inequality change (%)": pd.Series(inequality_changes).apply(lambda x : round(x * 100, 1)),
    "Winners (%)": pd.Series(percent_winners).apply(lambda x : round(x * 100, 1)),
    "Losers (%)": pd.Series(percent_losers).apply(lambda x : round(x * 100, 1))
}).set_index("UBI")
Poverty change (%) Deep poverty change (%) Inequality change (%) Winners (%) Losers (%)
UBI
£45 -17.0 -50.5 -2.8 69.9 16.2
£60 -21.8 -62.6 -3.5 71.7 14.8
£75 -30.1 -71.4 -4.4 81.2 5.5
£95 -38.5 -77.6 -5.4 85.9 0.8

Distributional effects

Inter-decile effects

The above effects only show the picture on the population as a whole. Below shows the average gain to members of the population by their household’s equivalised disposable income. With deficit funding, the plans are able to show positive impacts on average for every decile in every reform. Raising taxes to fund these proposals would likely create average losses for the higher deciles if the tax rises are progressive.

import plotly.graph_objects as go
from ubicenter import format_fig

fig = go.Figure()

income = baseline.calc("equiv_household_net_income", map_to="person")

for sim, name in zip(sims, names):
    gain = sim.calc("household_net_income", map_to="person") - baseline.calc("household_net_income", map_to="person")
    fig.add_trace(go.Bar(y=gain.groupby(income.decile_rank()).mean(), name=name))

format_fig(fig.update_layout(title="Gains by income decile", xaxis_tickvals=list(range(1, 11)), xaxis_title="Equivalised disposable income decile", yaxis_title="Absolute gain per year", yaxis_tickprefix="£"))

Intra-decile effects

There is some heterogeneity within the deciles, though not losses tend to be small. While the gains at the bottom of the income distribution are typically strong, the reforms are not particularly punitive on the top deciles either, which is to be expected given that the tax rises are limited to lower sections of income and, though to a smaller effect, changing the Personal Allowance explicitly does not affect those earning over £125,000 as it is phased out by this point. Below shows the distribution of outcomes for each decile, for each reform, including all individuals in the population.

import plotly.express as px
from charts import intra_decile_graph_data

intra = intra_decile_graph_data(baseline, *sims)

COLORS = [
        "#9E9E9E",
        "#E0E0E0",
        "#444444",
        "#C5E1A5",
        "#558B2F",
]

format_fig(px.bar(intra, x="fraction", y="decile", orientation="h", color="band", animation_frame="reform", color_discrete_sequence=COLORS).update_layout(
    yaxis_tickvals=list(range(1, 11)), 
    xaxis_tickformat="%", 
    yaxis_title="Income decile",
    xaxis_title="Outcome distributions",
    title="Intra-decile outcomes"
))

Individual effects

The above results show the impact on the population as it stands, but not the theoretical effects on household budgets. Below is shown the graph of household disposable income for a single person on Universal Credit.

from openfisca_uk import IndividualSim

def plot_budget(household_config, title):
    baseline_policy = IndividualSim()
    ubi_policy = IndividualSim(ubi_45)

    for policy in (baseline_policy, ubi_policy):
        household_config(policy)
        policy.vary("employment_income")

    fig = go.Figure()

    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=baseline_policy.calc("household_net_income")[0], name="Baseline"))
    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=ubi_policy.calc("household_net_income")[0], name="Reform"))
    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=baseline_policy.calc("tax")[0], name="Tax (Baseline)", visible="legendonly"))
    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=ubi_policy.calc("tax")[0], name="Tax (Reform)", visible="legendonly"))
    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=baseline_policy.calc("benefits")[0], name="Benefits (Baseline)", visible="legendonly"))
    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=ubi_policy.calc("benefits")[0], name="Benefits (Reform)", visible="legendonly"))
    fig.add_trace(go.Scatter(x=baseline_policy.calc("employment_income")[0], y=ubi_policy.calc("UBI")[0], name="UBI (Reform)", visible="legendonly"))

    from ubicenter import format_fig
    return format_fig(fig.update_layout(
        title=title,
        yaxis_tickprefix="£",
        xaxis_tickprefix="£",
        yaxis_title="Yearly amount",
        xaxis_title="Employment income",
    ))

def single_person_UC(sim):
    sim.add_person(age=26, is_benunit_head=True, name="adult"),
    sim.add_benunit(adults=["adult"], claims_UC=True),
    sim.add_household(adults=["adult"])

plot_budget(single_person_UC, "Budget for a single adult on Universal Credit")

Appendix

Additional details from the simulation and policies are given below.

Costing estimates

The Working Group used different modelling methods than were used in this analysis, resulting in our analysis producing higher net costs than the Working Group found. This is primarily due to the fact that this analysis used a household simulation method, rather than administrative data from HMRC. This allows for finer levels of detail and distributional analysis, but high incomes and benefit receipts are under-reported, causing an underestimate of the revenue raised by the tax reforms. The details are shown in the table below.

LD_lower = (13, 22, 48, 84)
LD_upper = (18, 28, 56, 93)
pd.DataFrame({
    "UBI": names, 
    "LD net cost (£bn)": [f"{low}-{high}" for low, high in zip(LD_lower, LD_upper)], 
    "Simulated net cost (£bn)": pd.Series(costs).apply(lambda x: round(x / 1e+9, 1)), 
    "UBI cost": pd.Series(ubi_cost).apply(lambda x: round(x / 1e+9, 1)),
    "Tax revenue": pd.Series([reform_tax_revenue] * len(ubi_cost)).apply(lambda x: round(x / 1e+9, 1)),
    "Reduced benefits": pd.Series(benefit_revenue).apply(lambda x: round(x / 1e+9, 1)),
    "Difference from central estimate (£bn)": [round((c - (low + high) / 2 * 1e+9) / 1e+9, 1) for c, low, high in zip(costs, LD_lower, LD_upper)],
}).set_index("UBI")
LD net cost (£bn) Simulated net cost (£bn) UBI cost Tax revenue Reduced benefits Difference from central estimate (£bn)
UBI
£45 13-18 21.8 95.1 79.7 -6.4 6.3
£60 22-28 34.3 126.9 79.7 12.8 9.3
£75 48-56 62.7 158.6 79.7 16.1 10.7
£95 84-93 100.7 200.9 79.7 20.5 12.2

Budgets for other household types

Below is a selection of the theoretical effects on different household types.

def couple_UC(sim):
    sim.add_person(age=26, is_benunit_head=True, name="adult"),
    sim.add_person(age=27, is_benunit_head=False, name="adult2"),
    sim.add_benunit(adults=["adult", "adult2"]),
    sim.add_household(adults=["adult", "adult2"])
    
plot_budget(couple_UC, "Couple on Universal Credit")
def couple_children_UC(sim):
    sim.add_person(age=26, is_benunit_head=True, name="adult"),
    sim.add_person(age=27, name="adult2"),
    sim.add_person(age=3, name="child"),
    sim.add_person(age=4, name="child2"),
    sim.add_benunit(adults=["adult", "adult2"], children=["child", "child2"], claims_UC=True, claims_child_benefit=True)
    sim.add_household(adults=["adult", "adult2"], children=["child", "child2"])
    
plot_budget(couple_children_UC, "Couple with two children on Universal Credit")

1

Universal Credit, Tax Credits, Housing Benefit and Income Support simulated. The UBI is treated as earned income, rather than as unearned income.